import { request } from '@weapp/utils';
import { uuid } from './uuid';

import { throttle } from 'lodash';

/* eslint-disable no-throw-literal */
declare global {
  interface Window {
    weapp: object;
    require: any;
    emRequire: any;
    attachEvent: any;
    opera: any;
    TEAMS: any;
    documentReady: any;
    WVJBCallbacks: any;
    WebViewJavascriptBridge: any;
  }
}

function emRequire() {
  return window.require || window.emRequire;
}

function langFormat(lang: string = '') {
  if (lang) {
    let dummy = lang.replace('_', '-');
    if (dummy.indexOf('en') === 0) {
      dummy = 'en-US';
    }
    return dummy;
  }
  return lang;
}

function relaunch() {
  const emr = emRequire();
  if (emr) {
    const { remote } = emr('electron');
    const { app } = remote;
    app.relaunch({
      args: process.argv.slice(1).concat(['--relaunch'])
    });

    app.exit(0);
  }
}

const broadcastEvents: Map<string, any> = new Map();
const broadcastIpcName = 'jssdk-broadcast';

const POST_MESSAGE_TYPE: any = 'weapp-emmessage';

const REGISTER_IM_NOTICE_FUNCNAME = 'registerImNotice';
const REMOVE_IM_LISTENER_FUNCNAME = 'removeImListener';
const PAGEVISIBLE_FUNCNAME = 'pageVisible';

class weappEmJsSdk {
  static weappUA: any;
  static WebViewJavascriptBridge: any;  // app的webview bridge
  static e10SupportArr: any[]           // e10 支持的方法
  static e10PcSupportArr: any[];        // e10 pc客户端支持的方法
  static iosSupportArr: any[];          // ios 支持的方法
  static androidSupportArr: any[];      // android 支持的方法

  static isE10AppOk: boolean;           // 在emapp环境并且getsupportjsapi回调
  static isE10PcOk: boolean;            // 在empc环境并且getsupportjsapi回调

  static callback: any;                 // 通知回调

  static iframeSuccess: any;            // iframe 成功回调
  static iframeFail: any;               // iframe 失败回调
  static iframeCallback: any;           // iframe callback回调

  static pageVisibleCallback: any;      // pageVisible的回调
  static fullScreenCallback: any;       // fullScreen的回调
  static meetingCallback: any;          // meeting 会议的回调

  static isPCIframeOk: any;             // pc iframe jssdk已经加载
  static pcTrackId: any;                // pc iframe track 唯一 id

  static copyImageIng: boolean;         // pc 正在复制图片【不允许重复复制】

  constructor() {
    weappEmJsSdk.e10SupportArr = ['login'];
    weappEmJsSdk.e10PcSupportArr = [];

    weappEmJsSdk.iosSupportArr = [];
    weappEmJsSdk.androidSupportArr = [];
    weappEmJsSdk.isE10AppOk = false;
    weappEmJsSdk.isE10PcOk = false;

    weappEmJsSdk.callback = {};

    weappEmJsSdk.iframeSuccess = {};
    weappEmJsSdk.iframeFail = {};
    weappEmJsSdk.iframeCallback = {};

    weappEmJsSdk.pageVisibleCallback = null;
    weappEmJsSdk.fullScreenCallback = null;
    weappEmJsSdk.meetingCallback = null;

    weappEmJsSdk.weappUA = window.navigator.userAgent;

    weappEmJsSdk.isPCIframeOk = false;

    if (weappEmJsSdk.inE10APP()) {
      weappEmJsSdk.checkBridge();
      weappEmJsSdk.getAllSupportJsapi();
    }

    if (weappEmJsSdk.inE10Pc()) { // 在 pc 客户端
      weappEmJsSdk.pageVisibleListener();
      weappEmJsSdk.fullScreenListener();
      weappEmJsSdk.e10PcSupportArr = [
        ...weappEmJsSdk.e10SupportArr,
        ...weappEmJsSdk.e10PcSupportArr,
        'switchServer', // 切换服务器地址
        'setWindowOpenHandler', // 新窗口打开事件
        'pageVisible',
        'fullScreen',
        'openLink',
        'maxmizeWindow',
        'minimizeWindow',
        'isMaximized',
        'isMinimized',
        'closeWindow',
        'isFullScreen',
        'setFullScreen',
        'cancelFullScreen',
        'toggleFullScreen',
        'refreshAllWindow',
        'copyImage',
        'isSyncSupport',
        'closePcClientWindow'
      ];

      weappEmJsSdk.getPcAllSupportJsapi();
    }

    const emr = emRequire();
    if (emr) {
      const electron = emr('electron');
      if (electron) {
        const { ipcRenderer } = electron;
        if (ipcRenderer) {
          ipcRenderer.on(broadcastIpcName, (event: any, args: any) => {
            const { name, param } = args;
            const cb = broadcastEvents.get(name);
            if (cb) {
              cb(param);
            }
          });
        }
      }
    }

    window.addEventListener('message', event => {
      const data: any = event.data || {};
      weappEmJsSdk.isPCIframeOk = true;

      const {
        type,
        funcName
      } = data;

      if (type !== POST_MESSAGE_TYPE) {
        return;
      }

      if (funcName === 'first') {
        window.parent.postMessage({
          type: POST_MESSAGE_TYPE,
          funcName: 'first'
        }, '*');

        const {
          res
        } = data;

        const result = res ? JSON.parse(res) : {};

        const {
          trackId = '',
          support = [],
        } = result;

        weappEmJsSdk.pcTrackId = trackId;
        weappEmJsSdk.e10SupportArr = [...weappEmJsSdk.e10SupportArr, ...support];

        return;
      }

      weappEmJsSdk.iframeListener(data);
    });
  }

  static iframeListener(data: any): void {
    const {
      res,
      funcName
    } = data;

    const result = res ? JSON.parse(res) : {};

    const {
      iframePostType,
      iframeCallbackFuncName
    } = result;

    if (iframePostType === 'success') { // 成功
      delete result.iframePostType;

      const success = weappEmJsSdk.iframeSuccess[funcName];

      weappEmJsSdk.objCallBack(result, success);
    }

    if (iframePostType === 'fail') { // 失败
      delete result.iframePostType;

      const fail = weappEmJsSdk.iframeFail[funcName];

      weappEmJsSdk.objCallBack(result, fail);
    }

    if (iframePostType === 'callback') { // 回调
      if (iframeCallbackFuncName === REGISTER_IM_NOTICE_FUNCNAME) {
        delete result.iframePostType;
        delete result.iframeCallbackFuncName;

        const {
          msg = {},
          iframeCmd,
          msg_type: msgType
        } = result;

        let finalMsg: any = msg;

        if (msg && Object.prototype.toString.apply(msg) === '[object String]') {
          finalMsg = JSON.parse(msg);
        }

        const {
          type = ''
        } = finalMsg || {};

        let funcKey = funcName;
        if (type) {
          funcKey = `${REGISTER_IM_NOTICE_FUNCNAME}-${iframeCmd}-${type}`;
        } else if (msgType) {
          funcKey = `${REGISTER_IM_NOTICE_FUNCNAME}-${iframeCmd}-${msgType}`;
        }

        // funcKey = `${REGISTER_IM_NOTICE_FUNCNAME}-${iframeCmd}-133`;
        const callback = weappEmJsSdk.iframeCallback[funcKey];
        callback && callback(result);
      }

      if (iframeCallbackFuncName === PAGEVISIBLE_FUNCNAME) {
        delete result.iframePostType;
        delete result.iframeCallbackFuncName;

        const {
          visible,
          unread
        } = result;

        const callback = weappEmJsSdk.iframeCallback[PAGEVISIBLE_FUNCNAME];

        callback && callback(visible, unread);
      }
    }
  }

  static inAndroid(): boolean {
    return weappEmJsSdk.weappUA.indexOf('Android') > -1;
  }

  static inIphone(): boolean {
    return weappEmJsSdk.weappUA.indexOf('iPhone') > -1 || weappEmJsSdk.weappUA.indexOf('iPad') > -1;
  }

  static inE10APP(): boolean {
    return weappEmJsSdk.weappUA.indexOf('weapp') > -1 && (weappEmJsSdk.weappUA.indexOf('Electron') < 0 && weappEmJsSdk.weappUA.indexOf('nw/') < 0);
  }

  static inE10Pc(): boolean {
    return weappEmJsSdk.weappUA.indexOf('weapp') > -1 && (weappEmJsSdk.weappUA.indexOf('Electron') > -1 || weappEmJsSdk.weappUA.indexOf('nw/') > -1);
  }

  static inMac(): boolean {
    return weappEmJsSdk.weappUA.indexOf('Mac') > -1 || weappEmJsSdk.weappUA.indexOf('mac') > -1;
  }

  /**
   * 判断版本号
   * @param compareVersion 需要比对的版本号
   * @param compareType lt: 小于 lte: 小于等于 gt: 大于 gte: 大于等于
   */
  static isVersion(compareVersion: string = '', compareType: string = 'gte'): boolean {
    // let uaArr = [];
    // if (weappEmJsSdk.weappUA.indexOf('eteams') >= 0) { // 正式版本
    //   uaArr = weappEmJsSdk.weappUA.split('eteams/');
    // }

    // if (weappEmJsSdk.weappUA.indexOf('weapp内测') >= 0) { // beta版本
    //   uaArr = weappEmJsSdk.weappUA.split('weapp内测/');
    // }

    // const uaOne = uaArr[1] || '';
    // const uaOArr = uaOne.split(' ');
    // const ua = uaOArr[0] || '';
    // const uas = ua.split('-');  // 有可能是x.x.x-beta
    // const final = uas[0] || '';
    // let version: any = final.replace(/[.]/g, '');  // 当前版本
    const emr = emRequire();
    const { remote } = emr('electron');
    let version = remote.app.getVersion();
    version = version.split('-')[0];
    version = version.replace(/[.]/g, '');
    if (!version) {
      version = 0;
    }

    let cv: any = compareVersion.replace(/[.]/g, ''); // 比对版本
    if (!cv) {
      cv = 0;
    }

    version = Number(version);
    cv = Number(cv);

    if (compareType === 'gte') {
      return version >= cv;
    }

    if (compareType === 'gt') {
      return version > cv;
    }

    if (compareType === 'lte') {
      return version <= cv;
    }

    if (compareType === 'lt') {
      return version < cv;
    }

    return false; // 默认给个false
  }

  static setBridge(): void {
    try {
      if (window.top && window.top.WebViewJavascriptBridge) {
        weappEmJsSdk.WebViewJavascriptBridge = window.top.WebViewJavascriptBridge;
      } else if (window.WebViewJavascriptBridge) {
        weappEmJsSdk.WebViewJavascriptBridge = window.WebViewJavascriptBridge;
      } else {
        weappEmJsSdk.WebViewJavascriptBridge = null;
      }
    } catch (error) {
      if (window.WebViewJavascriptBridge) {
        weappEmJsSdk.WebViewJavascriptBridge = window.WebViewJavascriptBridge;
      } else {
        weappEmJsSdk.WebViewJavascriptBridge = null;
      }
    }
  }

  static checkBridge(): void {
    weappEmJsSdk.setBridge();

    if (weappEmJsSdk.WebViewJavascriptBridge) { // 有了不要重复设置，就用之前的
      return;
    }

    if (!window.onerror) {
      window.onerror = function (msg, url, line) {
        console.log(`WebViewJavascriptBridge: ERROR:${msg}@${url}:${line}`);
      }
    }

    if (weappEmJsSdk.inIphone()) {
      if (window.WVJBCallbacks === undefined) {
        window.WVJBCallbacks = [
          (bridge: any) => { }
        ];

        let WVJBIframe = document.createElement('iframe');
        WVJBIframe.style.display = 'none';
        WVJBIframe.src = 'https://__bridge_loaded__';
        document.documentElement.appendChild(WVJBIframe);

        setTimeout(() => {
          document.documentElement.removeChild(WVJBIframe);
        });
      }

      let messagingIframe: any;
      let sendMessageQueue: any[] = [];
      let messageHandlers: any = {};

      let CUSTOM_PROTOCOL_SCHEME = 'https';
      let QUEUE_HAS_MESSAGE = '__wvjb_queue_message__';

      let responseCallbacks: any = {};
      let uniqueId = 1;
      let dispatchMessagesWithTimeoutSafety = true;

      const registerHandler = function (handlerName: any, handler: any) {
        messageHandlers[handlerName] = handler;
      }

      const _doSend = function (message: any, responseCallback: Function = () => { }) {
        if (responseCallback) {
          let callbackId = `cb_${uniqueId++}_${new Date().getTime()}`;
          responseCallbacks[callbackId] = responseCallback;
          message['callbackId'] = callbackId;
        }
        sendMessageQueue.push(message);
        messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
      }

      const callHandler = function (handlerName: any, data: any, responseCallback: Function = () => { }) {
        if (arguments.length == 2 && typeof data == 'function') {
          responseCallback = data;
          data = null;
        }
        _doSend({ handlerName: handlerName, data: data }, responseCallback);
      }

      const disableJavscriptAlertBoxSafetyTimeout = function () {
        dispatchMessagesWithTimeoutSafety = false;
      }

      const _fetchQueue = function () {
        let messageQueueString = JSON.stringify(sendMessageQueue);
        sendMessageQueue = [];
        return messageQueueString;
      }

      const _dispatchMessageFromObjC = function (messageJSON: any) {
        if (dispatchMessagesWithTimeoutSafety) {
          setTimeout(_doDispatchMessageFromObjC);
        } else {
          _doDispatchMessageFromObjC();
        }

        function _doDispatchMessageFromObjC() {
          let message = JSON.parse(messageJSON);
          let responseCallback;

          if (message.responseId) {
            responseCallback = responseCallbacks[message.responseId];
            if (!responseCallback) {
              return;
            }
            responseCallback(message.responseData);
            delete responseCallbacks[message.responseId];
          } else {
            if (message.callbackId) {
              let callbackResponseId = message.callbackId;
              responseCallback = function (responseData: any) {
                _doSend({ handlerName: message.handlerName, responseId: callbackResponseId, responseData: responseData }, () => { });
              };
            }

            let handler = messageHandlers[message.handlerName];
            if (!handler) {
              console.log('WebViewJavascriptBridge: WARNING: no handler for message from ObjC:', message);
            } else {
              handler(message.data, responseCallback);
            }
          }
        }
      }

      const _handleMessageFromObjC = function (messageJSON: any) {
        _dispatchMessageFromObjC(messageJSON);
      }

      window.WebViewJavascriptBridge = {
        registerHandler: registerHandler,
        callHandler: callHandler,
        disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout,
        _fetchQueue: _fetchQueue,
        _handleMessageFromObjC: _handleMessageFromObjC
      };

      messagingIframe = document.createElement('iframe');
      messagingIframe.style.display = 'none';
      messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
      document.documentElement.appendChild(messagingIframe);

      registerHandler('_disableJavascriptAlertBoxSafetyTimeout', disableJavscriptAlertBoxSafetyTimeout);

      const _callWVJBCallbacks = function () {
        let callbacks = window.WVJBCallbacks || [];
        delete window.WVJBCallbacks;
        for (let i = 0; i < callbacks.length; i++) {
          callbacks[i](window.WebViewJavascriptBridge);
        }
      }

      setTimeout(_callWVJBCallbacks, 0);
    } else if (weappEmJsSdk.inAndroid()) {
      let messagingIframe: any;
      let bizMessagingIframe: any;
      let sendMessageQueue: any[] = [];
      let receiveMessageQueue: any[] = [];
      let messageHandlers: any = {};

      let CUSTOM_PROTOCOL_SCHEME = 'yy';
      let QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/';

      let responseCallbacks: any = {};
      let uniqueId = 1;

      // 创建消息index队列iframe
      const _createQueueReadyIframe = function (doc: any) {
        messagingIframe = doc.createElement('iframe');
        messagingIframe.style.display = 'none';
        doc.documentElement.appendChild(messagingIframe);
      }

      //创建消息体队列iframe
      const _createQueueReadyIframe4biz = function (doc: any) {
        bizMessagingIframe = doc.createElement('iframe');
        bizMessagingIframe.style.display = 'none';
        doc.documentElement.appendChild(bizMessagingIframe);
      }

      //set default messageHandler  初始化默认的消息线程
      const init = function (messageHandler: any) {
        if (window.WebViewJavascriptBridge._messageHandler) {
          throw new Error('WebViewJavascriptBridge.init called twice');
        }
        window.WebViewJavascriptBridge._messageHandler = messageHandler;
        let receivedMessages = receiveMessageQueue;
        receiveMessageQueue = [];
        for (let i = 0; i < receivedMessages.length; i++) {
          _dispatchMessageFromNative(receivedMessages[i]);
        }
      }

      // 发送
      const send = function (data: any, responseCallback: Function = () => { }) {
        _doSend({
          data: data
        }, responseCallback);
      }

      // 注册线程 往数组里面添加值
      const registerHandler = function (handlerName: any, handler: any) {
        if (typeof handlerName == 'undefined' || handlerName == null || handlerName == '') {
          messageHandlers['emobile'] = handler;
        } else {
          messageHandlers[handlerName] = handler;
        }
      }

      //sendMessage add message, 触发native处理 sendMessage
      const _doSend = function (message: any, responseCallback: Function = () => { }) {
        if (responseCallback) {
          let callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();
          responseCallbacks[callbackId] = responseCallback;
          message.callbackId = callbackId;
        }

        sendMessageQueue.push(message);
        messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
      }

      // 调用线程
      const callHandler = function (handlerName: any, data: any, responseCallback: Function = () => { }) {
        _doSend({
          handlerName: handlerName,
          data: data
        }, responseCallback);
      }

      // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容
      const _fetchQueue = function () {
        let messageQueueString = JSON.stringify(sendMessageQueue);
        sendMessageQueue = [];
        //android can't read directly the return data, so we can reload iframe src to communicate with java
        if (messageQueueString !== '[]') {
          bizMessagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString);
        }
      }

      //提供给native使用,
      const _dispatchMessageFromNative = function (messageJSON: any) {
        setTimeout(function () {
          let message = JSON.parse(messageJSON);
          let responseCallback;
          //java call finished, now need to call js callback function
          if (message.responseId) {
            responseCallback = responseCallbacks[message.responseId];
            if (!responseCallback) {
              return;
            }
            responseCallback(message.responseData);
            delete responseCallbacks[message.responseId];
          } else {
            //直接发送
            if (message.callbackId) {
              let callbackResponseId = message.callbackId;
              responseCallback = function (responseData: any) {
                _doSend({
                  responseId: callbackResponseId,
                  responseData: responseData
                }, () => { });
              };
            }

            let handler = window.WebViewJavascriptBridge._messageHandler;
            if (message.handlerName) {
              handler = messageHandlers[message.handlerName];
            }
            //查找指定handler
            try {
              handler(message.data, responseCallback);
            } catch (exception) {
              if (typeof console != 'undefined') {
                console.log('WebViewJavascriptBridge: WARNING: javascript handler threw.', message, exception);
              }
            }
          }
        });
      }

      //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
      const _handleMessageFromNative = function (messageJSON: any) {
        if (receiveMessageQueue) {
          receiveMessageQueue.push(messageJSON);
        }
        _dispatchMessageFromNative(messageJSON);
      }

      window.WebViewJavascriptBridge = {
        init: init,
        send: send,
        registerHandler: registerHandler,
        callHandler: callHandler,
        _fetchQueue: _fetchQueue,
        _handleMessageFromNative: _handleMessageFromNative
      };

      let doc = document;
      _createQueueReadyIframe(doc);
      _createQueueReadyIframe4biz(doc);
      let readyEvent: any = null;
      readyEvent = doc.createEvent('Events');
      readyEvent.initEvent('WebViewJavascriptBridgeReady');
      readyEvent.bridge = window.WebViewJavascriptBridge;
      doc.dispatchEvent(readyEvent);
    }

    // 注册完了
    weappEmJsSdk.WebViewJavascriptBridge = window.WebViewJavascriptBridge;
  }

  static getPcAllSupportJsapi(): void {
    // 之前的版本号判断的
    if (weappEmJsSdk.isVersion('3.1.5')) { // 需要 >= 3.1.5
      weappEmJsSdk.e10PcSupportArr = [
        ...weappEmJsSdk.e10PcSupportArr,
        'getAllPrinters',
        'printUrl',
        'printPdf', // 下面的不知道有没有问题
        'printUrlInternal'
      ];

      // if (weappEmJsSdk.inMac() && weappEmJsSdk.isVersion('3.1.6')) {
      //   weappEmJsSdk.e10PcSupportArr = [...weappEmJsSdk.e10PcSupportArr, 'printPdf'];
      // } else {
      //   weappEmJsSdk.e10PcSupportArr = [...weappEmJsSdk.e10PcSupportArr, 'printPdf'];
      // }
    }

    let ipcRenderer: any = null;
    const emr = emRequire();
    if (emr) {
      ipcRenderer = emr('electron').ipcRenderer;
    }

    if (ipcRenderer) {
      if (weappEmJsSdk.isVersion('3.2.0')) { // 3.2.0 及其以上才有这个
        ipcRenderer.once('get-all-support-js-api.result', (event: any, args: any) => {
          const {
            res
          } = args;

          const finalRes = JSON.parse(res);
          weappEmJsSdk.isE10PcOk = true;
          weappEmJsSdk.e10PcSupportArr = [
            ...weappEmJsSdk.e10PcSupportArr,
            ...finalRes
          ];
        });

        ipcRenderer.send('get-all-support-js-api');
      } else {
        weappEmJsSdk.isE10PcOk = true;
      }
    } else {
      weappEmJsSdk.isE10PcOk = true;

      if (weappEmJsSdk.isVersion('3.2.0')) {
        weappEmJsSdk.e10PcSupportArr = [
          ...weappEmJsSdk.e10PcSupportArr,
          'joinMeeting',
          'systemIdentify',
          'chooseDirectroy',
          'relaunch',
          'chooseFile',
          'openSyncWindow',
          'syncRules',
          'noticeRuleChange',
          'downloadCloudFile',
          'uploadFileToCloud',
        ];
      }
    }
  }

  static getAllSupportJsapi(): void {
    const time = new Date().getTime();

    weappEmJsSdk.eMobileFunc({
      success: (res: any) => {
        const supportJsapi = res.supportJsapi || [];

        const newTime = new Date().getTime();

        console.error(`e10app getAllSupportJsapi supportJsapi ${newTime - time}: `, supportJsapi);

        if (supportJsapi.length > 0) {
          try {
            if (weappEmJsSdk.inAndroid()) {
              const uas = weappEmJsSdk.weappUA.split('weapp/');
              const uaTwo = uas[1] || '';
              const uats = uaTwo.split('/');
              const version = uats[0] || '';
              const appTag = uats[1] || '';
              const vs = version.split('.');
              const first = vs[0];
              const two = vs[1];
              const three = vs[2];

              let androidSupportArr: any = [...supportJsapi, 'pageVisible'];

              if (appTag === 'publicBeta' && first <= 4 && two <= 0 && three <= 210) { // <= 4.0.210 内测
                androidSupportArr = androidSupportArr.filter((v: any) => v !== 'previewImage');
              }

              if (appTag === 'public' && first <= 4 && two <= 0 && three <= 180) { // <= 4.0.180 正式
                androidSupportArr = androidSupportArr.filter((v: any) => v !== 'previewImage');
              }

              weappEmJsSdk.androidSupportArr = androidSupportArr;
            }

            if (weappEmJsSdk.inIphone()) {
              const uas = weappEmJsSdk.weappUA.split('weapp/');
              const uaTwo = uas[1] || '';
              const uats = uaTwo.split('/');
              const version = uats[0] || '';
              const appTag = uats[1] || '';
              const vs = version.split('.');
              const first = vs[0];
              const two = vs[1];
              const three = vs[2];

              let iosSupportArr: any = [...supportJsapi, 'pageVisible'];

              if (first <= 4 && two <= 3 && three <= 25 && (appTag === 'public' || appTag === 'eoffice' || appTag === 'private' || appTag === 'iphonegdcc')) { // <= 4.3.25
                iosSupportArr = iosSupportArr.filter((v: any) => v !== 'previewImage');
              }

              weappEmJsSdk.iosSupportArr = iosSupportArr;
            }
          } catch (error) {
            weappEmJsSdk.androidSupportArr = supportJsapi;
          }
        }

        weappEmJsSdk.isE10AppOk = true;
      }
    }, 'getAllSupportJsapi');
  }

  static eMobileFunc(params: any, funcName: String, func: Function = () => { }): void {
    if (weappEmJsSdk.inE10APP()) {
      if (!weappEmJsSdk.WebViewJavascriptBridge) {
        weappEmJsSdk.checkBridge();
      }

      const callback = function (response: any) {
        if (typeof response === 'string') {
          response = JSON.parse(response);
        }

        const errCode = response.errCode;
        params = params || {};

        if (errCode === 0) { //成功
          const success = params['success'];
          if (typeof success === 'function') {
            success(response);
          }

          if (funcName === 'unListen') {
            const event = params['event'];
            if (event) {
              weappEmJsSdk.callback[event] = [];
            }
          }
        } else if (errCode === -1) { // 取消
          const cancel = params['cancel'];
          if (typeof cancel === 'function') {
            cancel(response);
          }
        } else if (errCode !== 0) { // 失败
          const fail = params['fail'];
          if (typeof fail === 'function') {
            fail(response);
          }
        }

        const complete = params['complete']; // 完成
        if (typeof complete === 'function') {
          complete(response);
        }
      };

      if (func && Object.prototype.toString.apply(func) === '[object Function]') {
        console.error(`e10app ${funcName}: `, params);

        func(params);
      }

      weappEmJsSdk.WebViewJavascriptBridge.callHandler(funcName, params, callback);
    }
  }

  static eMobileRegisterHandler(name: any, obj: any, type: any, parse = false): void {
    if (type === 1) {
      const func = obj[name];

      if (func && Object.prototype.toString.apply(func) === '[object Function]') {
        weappEmJsSdk.WebViewJavascriptBridge.registerHandler(name, function (params: any) {
          if (parse && typeof params === 'string') {
            params = JSON.parse(params);
          }

          func(params);
        });
      }
    } else if (type === 2) {
      if (obj && Object.prototype.toString.apply(obj) === '[object Function]') {
        weappEmJsSdk.WebViewJavascriptBridge.registerHandler(name, function (params: any) {
          obj(params);
        });
      }
    } else if (type === 3) {
      if (obj) {
        let mainAction = obj['action'];
        let mainName = obj['name'];
        let subItems = obj['subItems'];
        if (mainAction) {
          weappEmJsSdk.WebViewJavascriptBridge.registerHandler(mainName, function (params: any, responseCallback: Function = () => { }) {
            mainAction(params);
            responseCallback(obj);
          });
        } else if (subItems instanceof Array) {
          for (let i = 0; i < subItems.length; i++) {
            let subItem = subItems[i];
            let subAction = subItem['action'];
            let subName = subItem['name'];
            if (subAction) {
              weappEmJsSdk.WebViewJavascriptBridge.registerHandler(subName, function (params: any, responseCallback: Function = () => { }) {
                subAction(params);
                responseCallback(obj);
              });
            }
          }
        }
      }
    } else if (type === 4) {
      const mainName = obj['name'];
      const callback = obj['callback'];
      if (mainName && Object.prototype.toString.apply(callback) === '[object Function]') {
        weappEmJsSdk.WebViewJavascriptBridge.registerHandler(mainName, function (params: any) {
          callback(params);
        });
      }
    } else if (type === 5) {
      const action = obj['action'];
      const name = obj['name'];
      weappEmJsSdk.WebViewJavascriptBridge.registerHandler(name, function (params: any, responseCallback: Function = () => { }) {
        action(params);
        responseCallback(obj);
      });
    } else if (type === 6) {
      const funcArr = weappEmJsSdk.callback[name] || [];

      weappEmJsSdk.WebViewJavascriptBridge.registerHandler(name, function (params: any) {
        funcArr.forEach((func: any) => {
          if (func && Object.prototype.toString.apply(func) === '[object Function]') {
            let finalParams = params;

            // 如果 listen返回的是JSON字符串, 转为对象
            if (finalParams && Object.prototype.toString.apply(finalParams) === '[object String]') {
              finalParams = JSON.parse(finalParams);
            }

            func(finalParams);
          }
        });
      });
    }
  }

  static objCallBack(obj: any, callback: Function = () => { }): void {
    if (callback && Object.prototype.toString.apply(callback) === '[object Function]') {
      callback(obj);
    }
  }

  static checkJsApi(data: any): any {
    if (data && Object.prototype.toString.apply(data) === '[object String]') {
      if (weappEmJsSdk.inE10APP()) {
        if (weappEmJsSdk.inAndroid()) {
          return weappEmJsSdk.androidSupportArr.indexOf(data) > -1;
        } else if (weappEmJsSdk.inIphone()) {
          return weappEmJsSdk.iosSupportArr.indexOf(data) > -1;
        }
      }

      if (weappEmJsSdk.inE10Pc()) {
        return weappEmJsSdk.e10PcSupportArr.indexOf(data) > -1;
      }

      return weappEmJsSdk.e10SupportArr.indexOf(data) > -1;
    } else if (data && Object.prototype.toString.apply(data) === '[object Object]') {
      if (weappEmJsSdk.inE10APP()) {
        weappEmJsSdk.eMobileFunc(data, 'checkJsApi');
        return;
      }

      const checkFunc = (obj: any, checkArr: string[]) => {
        let checkResult = {};
        obj.jsApiList.map((v: any) => {
          if (checkArr.indexOf(v) > -1) {
            checkResult = {
              ...checkResult,
              [v]: true
            };
          } else {
            checkResult = {
              ...checkResult,
              [v]: false
            };
          }
        });

        weappEmJsSdk.objCallBack({
          checkResult: checkResult,
          errMsg: 'checkJsApi: ok'
        }, obj.success);
      }

      try {
        if (data.jsApiList && Object.prototype.toString.apply(data.jsApiList) === '[object Array]') {
          if (weappEmJsSdk.inE10Pc()) {
            checkFunc(data, weappEmJsSdk.e10PcSupportArr);
          } else {
            checkFunc(data, weappEmJsSdk.e10SupportArr);
          }
        } else {
          throw '参数不正确哦，jsApiList应该传入一个数组';
        }
      } catch (error) {
        weappEmJsSdk.objCallBack({
          errMsg: `checkJsApi: ${error}`
        }, data.fail);
      }

      weappEmJsSdk.objCallBack({
        errMsg: 'checkJsApi: complete'
      }, data.complete);
    } else {
      return false;
    }
  }

  static invoke(funcName: string, obj: any, callback: Function = () => { }): void {
    weappEmJsSdk.ready(() => {
      if (weappEmJsSdk.inE10APP()) {
        if (funcName.indexOf('listen') === 0 || funcName.indexOf('on') === 0 || funcName.indexOf('notify') === 0) {  // listenVisible, listenShake, listenReturn [listen, on, notify 开头的都需要监听]
          const funcArr = weappEmJsSdk.callback[funcName] || [];
          weappEmJsSdk.callback[funcName] = [...funcArr, obj.callback];

          weappEmJsSdk.eMobileFunc(obj, funcName, () => {
            weappEmJsSdk.eMobileRegisterHandler(funcName, {}, 6);
          });

          return;
        }

        switch (funcName) {
          case 'uploadFile':  // 根据本地ID上传到服务端
            weappEmJsSdk.eMobileFunc(obj, 'uploadFile', callback);
            weappEmJsSdk.eMobileRegisterHandler('onProgress', obj, 1); // 上传进度回调

            break;
          case 'getLocation': // 定位, 持续定位
            weappEmJsSdk.eMobileFunc(obj, 'getLocation');
            weappEmJsSdk.eMobileRegisterHandler('onLocationChanged', obj, 1); // 持续定位

            break;
          case 'pageVisible': // 页面是否显示
            weappEmJsSdk.invoke('appEventListener', {
              'name': 'KPageVisibleNotificationName',
              'action': (argument: any) => {
                const data = Object.prototype.toString.apply(argument) === '[object String]' ? JSON.parse(argument) : argument;
                obj(data.visible); // 这里的obj是一个function
              }
            });

            break;
          case 'appEventListener':  // 注册监听
            weappEmJsSdk.eMobileFunc(obj, 'appEventListener', (params: any) => {
              weappEmJsSdk.eMobileRegisterHandler('', params, 4);
            });

            break;
          case 'showPopup': // 标题弹出框
            weappEmJsSdk.eMobileFunc(obj, 'showPopup', (params: any) => {
              const items = params['items'] || [];
              items.map((item: any) => {
                weappEmJsSdk.eMobileRegisterHandler('', item, 5);
              });
            });

            break;
          case 'showBottomToolBar': // 底部菜单栏
            weappEmJsSdk.eMobileFunc(obj, 'showBottomToolBar', (params: any) => {
              const items = params['items'] || [];
              items.map((item: any) => {
                weappEmJsSdk.eMobileRegisterHandler('', item, 3);
              });
            });

            break;
          case 'setupBottomMenu': // 更多菜单
            weappEmJsSdk.eMobileFunc(obj, 'setupBottomMenu', (params: any) => {
              const items = params['items'] || [];
              items.map((item: any) => {
                weappEmJsSdk.eMobileRegisterHandler('', item, 5);
              });
            });

            break;
          case 'showTopToolBar': // 顶部
            weappEmJsSdk.eMobileFunc(obj, 'showTopToolBar', (params: any) => {
              const left = params['left'];
              const right = params['right'];
              const items = params['items'] || [];
              weappEmJsSdk.eMobileRegisterHandler('', left, 3);
              weappEmJsSdk.eMobileRegisterHandler('', right, 3);

              items.map((item: any) => {
                weappEmJsSdk.eMobileRegisterHandler('', item, 3);
              });
            });

            break;
          case 'speechTotext': // 语音转文字
            weappEmJsSdk.eMobileFunc(obj, 'continueSpeech', (params: any) => {
              weappEmJsSdk.eMobileRegisterHandler('speechTotext', params, 1);
            });

            break;
          case 'continueSpeech': // 语音听写
            weappEmJsSdk.eMobileFunc(obj, 'continueSpeech', (params: any) => {
              ['changeVoice', 'continueSpeechend', 'onContinueSpeech'].forEach(v => {
                weappEmJsSdk.eMobileRegisterHandler(v, params, 1, v !== 'changeVoice');
              });
            });

            break;
          case 'registerBroadcast': // 注册广播
            weappEmJsSdk.eMobileFunc(obj, 'registerBroadcast', (params: any) => {
              weappEmJsSdk.eMobileRegisterHandler('', params, 4);
            });

            break;
          case 'configNavigation': // 配置导航栏
            weappEmJsSdk.eMobileFunc(obj, 'configNavigation', (params: any) => {
              const left = params['left'];
              const right = params['right'];
              weappEmJsSdk.eMobileRegisterHandler('', left, 3);
              weappEmJsSdk.eMobileRegisterHandler('', right, 3);
            });

            break;
          case 'reloadStorage': // 不带参数刷新
            weappEmJsSdk.eMobileRegisterHandler('reloadStorage', obj, 2);

            break;
          case 'reloadStorageWithParams': // 带参数刷新
            weappEmJsSdk.eMobileRegisterHandler('reloadStorageWithParams', obj, 2);

            break;
          case 'registerHandler':
            const registerFunc = () => {
              const {
                fn,
                name = 'defaultRegisterHandler'
              } = obj || {};

              weappEmJsSdk.WebViewJavascriptBridge.registerHandler(name, function (params: any, responseCallback: any) {
                if (typeof params === 'string') {
                  params = JSON.parse(params);
                }

                if (fn && Object.prototype.toString.apply(fn) === '[object Function]') {
                  const res = fn(params);

                  if (responseCallback) {
                    responseCallback(res);
                  }
                }
              });
            }

            if (!weappEmJsSdk.WebViewJavascriptBridge) {  // 不存在
              weappEmJsSdk.checkBridge();
              registerFunc();
            } else {
              registerFunc();
            }

            weappEmJsSdk.eMobileFunc(obj, funcName, callback);

            break;
          case 'showMsg':
            if (!obj.msg) {
              obj.msg = {};
            }

            let finalMsg = obj.msg.msg || '';

            if (Object.prototype.toString.apply(finalMsg) === '[object Object]') {
              finalMsg = JSON.stringify(finalMsg);

              obj.msg.msg = finalMsg;
            }

            weappEmJsSdk.eMobileFunc(obj, funcName, callback);

            break;
          case 'joinMeeting':
            weappEmJsSdk.eMobileFunc(obj, funcName, callback);
            weappEmJsSdk.eMobileRegisterHandler('meetingCallback', obj, 1);

            break;
          default:
            weappEmJsSdk.eMobileFunc(obj, funcName, callback);

            break;
        }

        return;
      }

      if (weappEmJsSdk.inE10Pc()) {
        switch (funcName) {
          case 'pageVisible':
            weappEmJsSdk.pageVisibleCallback = obj;
            break;

          case 'openLink':
            weappEmJsSdk.openLink(obj);
            break;

          case 'copyImage':
            weappEmJsSdk.copyImage(obj);
            break;

          case 'fullScreen':
            weappEmJsSdk.fullScreenCallback = obj;
            weappEmJsSdk.fullScreenListener('first');
            break;

          case 'closeWindow':
            weappEmJsSdk.closeWindow(obj);
            break;

          case 'maxmizeWindow':
            weappEmJsSdk.maxmizeWindow(obj);
            break;

          case 'minimizeWindow':
            weappEmJsSdk.minimizeWindow(obj);
            break;

          case 'isMinimized':
            weappEmJsSdk.isMinimized(obj);
            break;

          case 'isMaximized':
            weappEmJsSdk.isMaximized(obj);
            break;

          case 'isFullScreen':
            weappEmJsSdk.isFullScreen(obj);
            break;

          case 'setFullScreen':
            weappEmJsSdk.setFullScreen(obj);
            break;

          case 'cancelFullScreen':
            weappEmJsSdk.cancelFullScreen(obj);
            break;

          case 'toggleFullScreen':
            weappEmJsSdk.toggleFullScreen(obj);
            break;

          case 'refreshAllWindow':
            weappEmJsSdk.refreshAllWindow(obj);
            break;

          case 'getAllPrinters':
            weappEmJsSdk.getAllPrinters(obj);
            break;

          case 'printUrl':
            weappEmJsSdk.printUrl(obj);
            break;

          case 'printUrlInternal':
            weappEmJsSdk.printUrlInternal(obj);
            break;

          case 'printPdf':
            weappEmJsSdk.printPdf(obj);
            break;

          case 'systemIdentify':
            weappEmJsSdk.systemIdentify(obj);
            break;

          case 'chooseDirectroy':
            weappEmJsSdk.chooseDirectroy(obj);
            break;

          case 'openSyncWindow':
            weappEmJsSdk.openSyncWindow(obj);
            break;

          case 'openLocalFolder':
            weappEmJsSdk.openLocalFolder(obj);
            break;

          case 'getRuleSyncState':
            weappEmJsSdk.getRuleSyncState(obj);
            break;

          case 'subscribeRuleStateChange':
            weappEmJsSdk.subscribeRuleStateChange(obj);
            break;

          case 'getLastLoginInfo':
            weappEmJsSdk.getLastLoginInfo(obj);
            break;

          case 'getLangLabels':
            weappEmJsSdk.getLangLabels(obj);
            break;

          case 'setLangLabelInfo':
            weappEmJsSdk.setLangLabelInfo(obj);
            break;

          case 'syncRules':
            weappEmJsSdk.syncRules(obj);
            break;

          case 'noticeRuleChange':
            weappEmJsSdk.noticeRuleChange(obj);
            break;

          case 'chooseFile':
            weappEmJsSdk.chooseFile(obj);
            break;

          case 'downloadCloudFile':
            weappEmJsSdk.downloadCloudFile(obj);
            break;

          case 'uploadFileToCloud':
            weappEmJsSdk.uploadFileToCloud(obj);
            break;

          case 'joinMeeting':
            weappEmJsSdk.joinMeeting(obj);
            break;

          case 'registerBroadcast':
            weappEmJsSdk.registerBroadcast(obj);
            break;

          case 'unregisterAllBroadcast':
            weappEmJsSdk.unregisterAllBroadcast(obj);
            break;

          case 'unregisterBroadcast':
            weappEmJsSdk.unregisterBroadcast(obj);
            break;

          case 'postBroadcast':
            weappEmJsSdk.postBroadcast(obj);
            break;

          case 'switchServer':
            weappEmJsSdk.switchServer(obj);
            break;

          case 'setWindowOpenHandler':
            weappEmJsSdk.setWindowOpenHandler(obj);
            break;

          case 'login':
            weappEmJsSdk.login(obj);
            break;

          case 'relaunch':
            weappEmJsSdk.relaunch(obj);
            break;

          case 'isSyncSupport':
            weappEmJsSdk.isSyncSupport(obj);
            break;

          case 'independentPhotoView':
            weappEmJsSdk.independentPhotoView(obj);
            break;

          case 'closePcClientWindow':
            weappEmJsSdk.closePcClientWindow(obj);
            break;

          case 'uploadFilePcClient':
            weappEmJsSdk.uploadFilePcClient(obj);
            break;

          case 'getUploadFiles':
            weappEmJsSdk.getUploadFiles(obj);
            break;
        }

        return;
      }

      if (funcName === REMOVE_IM_LISTENER_FUNCNAME) {
        const {
          cmd,
          type,
          msgType,
          funcName: oFuncName
        } = obj;

        if (oFuncName === REGISTER_IM_NOTICE_FUNCNAME) {
          let funcKey = oFuncName;

          if (type) {
            funcKey = `${REGISTER_IM_NOTICE_FUNCNAME}-${cmd}-${type}`;
          } else if (msgType) {
            funcKey = `${REGISTER_IM_NOTICE_FUNCNAME}-${cmd}-${msgType}`;
          }

          weappEmJsSdk.iframeCallback[funcKey] = null;
        }
      }

      weappEmJsSdk.postMsg(funcName, obj);
    });
  }

  static pageVisibleListener(): void {
    const handleVisible = (visible: boolean) => {
      if (Object.prototype.toString.apply(weappEmJsSdk.pageVisibleCallback) === '[object Function]') {
        weappEmJsSdk.pageVisibleCallback(visible);
      }
    }

    window.addEventListener('blur', () => handleVisible(false));
    window.addEventListener('focus', () => handleVisible(true));
  }

  static fullScreenListener(type: string = ''): void {
    const handleFull = (full: boolean) => {
      if (Object.prototype.toString.apply(weappEmJsSdk.fullScreenCallback) === '[object Function]') {
        weappEmJsSdk.fullScreenCallback(full);
      }
    }

    let remote: any = null;
    const emr = emRequire();
    if (emr) {
      remote = emr('electron').remote;
    }

    if (remote) {
      const currentWin = remote.getCurrentWindow();

      if (currentWin) {
        if (type === 'first') { // 首次获取
          const full = currentWin.fullScreen;

          handleFull(full);
        } else {
          currentWin.on('enter-full-screen', () => handleFull(true));
          currentWin.on('leave-full-screen', () => handleFull(false))
        }
      }
    }
  }

  static login(obj: any): void {
    try {
      let ipcRenderer: any = null;
      const emr = emRequire();
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        // weapp.invoke("login", {
        //   loginkey: "xxx", //string 类型。必填，身份认证标识，即eteamsid
        //   tenantid: "xxx", //string 类型。必填，租户id，区分租户
        //   cid: "xxx", //string 类型。非必填，消息服务中的团队标识cid
        //   userid: "xxx", //string 类型。必填，用户在租户下的ID，即employeeId
        //   langid: "", //非必填，语言标识，7、8、9等
        //   username: "xxx", //string 类型。非必填，用户登录账户，如果登录页面上用户勾选允许记住用户名则可以传递过来，用户后续app中切换账号时再传递给登录页面
        //   password: "xxx", //string 类型。非必填，用户登录密码，如果登录页面上用户勾选允许记住密码则可以传递过来，用户后续app中切换账号时再传递给登录页面
        // });
        const {
          loginkey: eid,
          tenantid: tid,
          cid,
          userid: uid,
          langid: lid,
        } = obj;

        if (weappEmJsSdk.inE10Pc()) {
          ipcRenderer.send('set-global-varible', {
            name: 'eteamsid',
            value: eid
          });

          // 设置客户端多语言
          let currentLocale = 'en-US';
          if (window.TEAMS?.locale) {
            const lang = window.TEAMS.locale.lang;
            currentLocale = langFormat(lang);

            ipcRenderer.send('set-global-varible', {
              name: 'web-last-lang',
              value: currentLocale,
              disk: true, // 保存到缓存文件，下次打开客户端要用
            });

            ipcRenderer.send('change-menu-locale', {
              locale: currentLocale
            });
          }

          // @ts-ignore
          if (window.__ET_CLIENT_SYNC_NEW) {
            // 文档同步
            const headers = {
              // @ts-ignore
              eteamsid: window.ETEAMSID
            };

            ipcRenderer.send('start-auto-sync', {
              url: window.location.host === 'weapp.develop.cn'
                ? 'https://weapp.yunteams.cn'
                : window.location.origin,
              header: headers,
              locale: currentLocale,
            });
          }
        }

        weappEmJsSdk.objCallBack({
          errMsg: 'login: ok',
          errCode: 0,
        }, obj.success);
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `login: ${error}`,
        errCode: 666, // 不是 0 就是失败了。
      }, obj.fail);
    }
  }

  static relaunch(obj: any): void {
    try {
      relaunch();

      weappEmJsSdk.objCallBack({
        errMsg: 'relaunch: ok'
      }, obj.success);
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `relaunch: ${error}`
      }, obj.fail);
    }
  }

  static closeWindow(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const { id } = obj;
        if (!id) { // 没有 id 就是关闭当前窗口
          const currentWin = remote.getCurrentWindow();
          currentWin.close();
        } else {
          const win = remote.BrowserWindow.fromId(id);
          if (win) {
            win.close();
          } else {
            throw new Error(`window is not exist, id: ${id}`);
          }
        }

        weappEmJsSdk.objCallBack({
          errMsg: 'closeWindow: ok'
        }, obj.success);
      } else {
        throw new Error(`remote is undefined`);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `closeWindow: ${error}`
      }, obj.fail);
    }
  }

  static maxmizeWindow(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();

      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const currentWin = remote.getCurrentWindow();

        if (currentWin) {
          const {
            max
          } = obj;

          if (max !== undefined) { // 手动设置
            max ? currentWin.maximize() : currentWin.unmaximize();
          } else { // 根据当前窗口是否是最大化
            const isMax = currentWin.isMaximized();
            !isMax
              ? currentWin.maximize()
              : currentWin.unmaximize();
          }

          weappEmJsSdk.objCallBack({
            errMsg: 'maxmizeWindow: ok'
          }, obj.success);
        } else {
          throw 'currentWin is undefined';
        }
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `maxmizeWindow: ${error}`
      }, obj.fail);
    }
  }

  static minimizeWindow(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const currentWin = remote.getCurrentWindow();

        if (currentWin) {
          currentWin.minimize();

          weappEmJsSdk.objCallBack({
            errMsg: 'minimizeWindow: ok'
          }, obj.success);
        } else {
          throw 'currentWin is undefined';
        }
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `minimizeWindow: ${error}`
      }, obj.fail);
    }
  }

  static isMinimized(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const currentWin = remote.getCurrentWindow();

        if (currentWin) {
          weappEmJsSdk.objCallBack({
            errMsg: 'isMinimized: ok',
            result: currentWin.isMinimized(),
          }, obj.success);
        } else {
          throw 'currentWin is undefined';
        }
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `isMinimized: ${error}`
      }, obj.fail);
    }
  }

  static isMaximized(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const currentWin = remote.getCurrentWindow();
        if (currentWin) {
          weappEmJsSdk.objCallBack({
            errMsg: 'isMaximized: ok',
            result: currentWin.isMaximized(),
          }, obj.success);
        } else {
          throw 'currentWin is undefined';
        }
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `isMaximized: ${error}`
      }, obj.fail);
    }
  }

  static isFullScreen(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const currentWin = remote.getCurrentWindow();
        if (currentWin) {
          weappEmJsSdk.objCallBack({
            errMsg: 'isFullScreen: ok',
            result: currentWin.isFullScreen(),
          }, obj.success);
        } else {
          throw 'currentWin is undefined';
        }
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `isFullScreen: ${error}`
      }, obj.fail);
    }
  }

  static setFullScreen(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const currentWin = remote.getCurrentWindow();
        if (currentWin) {
          currentWin.setFullScreen(1);
          weappEmJsSdk.objCallBack({
            errMsg: 'setFullScreen: ok',
            result: true,
          }, obj.success);
        } else {
          throw 'currentWin is undefined';
        }
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `setFullScreen: ${error}`
      }, obj.fail);
    }
  }

  static cancelFullScreen(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const currentWin = remote.getCurrentWindow();
        if (currentWin) {
          currentWin.setFullScreen(0);
          weappEmJsSdk.objCallBack({
            errMsg: 'cancelFullScreen: ok',
          }, obj.success);
        } else {
          throw 'currentWin is undefined';
        }
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `cancelFullScreen: ${error}`
      }, obj.fail);
    }
  }

  static toggleFullScreen(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const currentWin = remote.getCurrentWindow();
        if (currentWin) {
          currentWin.setFullScreen(currentWin.isFullScreen() ? 0 : 1)
          weappEmJsSdk.objCallBack({
            errMsg: 'toggleFullScreen: ok',
          }, obj.success);
        } else {
          throw 'currentWin is undefined';
        }
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `toggleFullScreen: ${error}`
      }, obj.fail);
    }
  }

  static refreshAllWindow(obj: any): void {
    try {
      let remote: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const allWindows = remote.BrowserWindow.getAllWindows();
        if (allWindows && allWindows.length) {
          const refreshList = ["download", "preference", "main", "update", "agent"];
          allWindows.forEach((win: any) => {
            if (win && win.webContents && win.oliType && (refreshList.indexOf(win.oliType) > -1)) {
              win.webContents.reload();
            }
          });
        }
        weappEmJsSdk.objCallBack({
          errMsg: 'refreshAllWindow: ok',
        }, obj.success);
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `refreshAllWindow: ${error}`
      }, obj.fail);
    }
  }

  static isSyncSupport(obj: any): void {
    try {
      // @ts-ignore
      const isSupport = Boolean(window.__ET_CLIENT_SYNC_NEW);
      weappEmJsSdk.objCallBack({
        errMsg: 'isSyncSupport: ok',
        sync: isSupport,
      }, obj.success);
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `isSyncSupport: ${error}`,
        sync: false,
      }, obj.fail);
    }
  }

  static getAllPrinters(obj: any): void {
    try {
      let ipcRenderer: any = null;
      const emr = emRequire();
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        let printers = ipcRenderer.sendSync('get-all-printers');
        if (!printers) {
          printers = [];
        }

        weappEmJsSdk.objCallBack({
          errMsg: 'getAllPrinters: ok',
          printers
        }, obj.success);
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `getAllPrinters: ${error}`
      }, obj.fail);
    }
  }

  static printUrl(obj: any): void {
    try {
      let remote: any = null;
      let ipcRenderer: any = null;
      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        const finalUrl = obj.url;

        ipcRenderer.send('print-url', {
          url: finalUrl
        });

        ipcRenderer.once('print-url-finish', (event: any, args: any) => {
          const {
            url,
            reason,
            success
          } = args;

          if (success) {
            weappEmJsSdk.objCallBack({
              errMsg: `printUrl: ${url} ok`
            }, obj.success);
          } else {
            weappEmJsSdk.objCallBack({
              errMsg: `printUrl: ${url} fail, reason: ${JSON.stringify(reason)}`
            }, obj.success);
          }
        });

        ipcRenderer.once('print-current-win-finish', (event: any, args: any) => {
          const {
            success
          } = args;

          if (success) {
            remote.getCurrentWindow().close();
          }
        });
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `printUrl: ${error}`
      }, obj.fail);
    }
  }

  static printUrlInternal(obj: any): void {
    try {
      const emr = emRequire();

      let ipcRenderer: any = null;
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        const finalUrl = obj.url;

        if (!finalUrl) {
          throw 'url is undefined';
        }

        ipcRenderer.send('print-url-internal', {
          url: finalUrl
        });

        ipcRenderer.once('print-url-internal-finish', (event: any, args: any) => {
          const {
            url,
            reason,
            success
          } = args;

          if (success) {
            weappEmJsSdk.objCallBack({
              errMsg: `printUrlInternal: ${url} ok`
            }, obj.success);
          } else {
            weappEmJsSdk.objCallBack({
              errMsg: `printUrlInternal: ${url} fail, reason: ${JSON.stringify(reason)}`
            }, obj.success);
          }
        })
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `printUrlInternal: ${error}`
      }, obj.fail);
    }
  }

  static printPdf(obj: any): void {
    try {
      const emr = emRequire();

      let ipcRenderer: any = null;
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        const finalUrl = obj.url;

        if (!finalUrl) {
          throw 'url is undefined';
        }

        ipcRenderer.send('print-pdf', {
          url: finalUrl
        });

        ipcRenderer.once('print-pdf-finish', (event: any, args: any) => {
          const {
            url,
            reason,
            success
          } = args;

          if (success) {
            weappEmJsSdk.objCallBack({
              errMsg: `printPdf: ${url} ok`
            }, obj.success);
          } else {
            weappEmJsSdk.objCallBack({
              errMsg: `printPdf: ${url} fail, reason: ${JSON.stringify(reason)}`
            }, obj.success);
          }
        })
      } else {
        throw new Error('ipcRenderer is undefined');
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `printPdf: ${error}`
      }, obj.fail);
    }
  }

  static openLink(obj: any): void {
    try {
      const emr = emRequire();

      let ipcRenderer: any = null;
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        const {
          url
        } = obj;

        ipcRenderer.invoke('shell-open-external', { url });

        weappEmJsSdk.objCallBack({
          errMsg: 'openLink: ok'
        }, obj.success);
      } else {
        throw new Error('ipcRenderer is undefined');
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `openLink: ${error}`
      }, obj.fail);
    }
  }

  static copyImage(obj: any) {
    if (false) { // 先屏蔽掉了
      // if (weappEmJsSdk.e10PcSupportArr.indexOf('clientCopyImage') > -1) {
      try {
        const {
          url
        } = obj;

        let ipcRenderer: any = null;

        const emr = emRequire();
        if (emr) {
          ipcRenderer = emr('electron').ipcRenderer;
        }

        if (ipcRenderer) {
          ipcRenderer.send('copy-image', {
            imageUrl: url
          });

          ipcRenderer.once('copy-image-success', () => {
            weappEmJsSdk.objCallBack({
              errMsg: 'copyImage: ok',
            }, obj.success);
          });

          ipcRenderer.once('copy-image-fail', (event: any, data: any) => {
            const {
              error = ''
            } = data || {};

            weappEmJsSdk.objCallBack({
              errMsg: `copyImage: ${error}`
            }, obj.fail);
          });
        }
      } catch (error) {
        weappEmJsSdk.objCallBack({
          errMsg: `copyImage: ${error}`
        }, obj.fail);
      }
    } else {
      const imageUrlToDataURL = (url: string) => {
        return new Promise((resolve, reject) => {
          const img = new Image();

          // 允许资源跨域使用
          img.setAttribute('crossOrigin', 'anonymous');
          img.src = url;

          img.onload = function () {
            const imgWidth = img.width;
            const imgHeight = img.height;

            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            canvas.width = imgWidth;
            canvas.height = imgHeight;

            ctx?.drawImage(img, 0, 0, imgWidth, imgHeight);
            // const type = 'image/png';
            const dataURL = canvas.toDataURL();
            resolve(dataURL);
          };

          img.onerror = function (e) {
            // console.error('imageUrlToDataURL error', e);
            reject(e);
          };
        });
      }

      try {
        // 之前图片没复制完，可能导致pc卡死
        if (weappEmJsSdk.copyImageIng) {
          return;
        }

        const {
          url
        } = obj;

        weappEmJsSdk.copyImageIng = true;

        imageUrlToDataURL(url).then((dataUrl: any) => {
          const { remote } = window.emRequire('electron');

          const nativeImage = remote.nativeImage;
          const img = nativeImage.createFromDataURL(dataUrl);

          remote.clipboard.writeImage(img);

          weappEmJsSdk.copyImageIng = false;

          weappEmJsSdk.objCallBack({
            errMsg: 'copyImage: ok',
          }, obj.success);
        }).catch((error: any) => {
          weappEmJsSdk.copyImageIng = false;

          weappEmJsSdk.objCallBack({
            errMsg: `copyImage: ${error}`
          }, obj.fail);
        });
      } catch (error) {
        weappEmJsSdk.copyImageIng = false;

        weappEmJsSdk.objCallBack({
          errMsg: `copyImage: ${error}`
        }, obj.fail);
      }
    }
  }

  static unregisterAllBroadcast(obj: any): void {
    try {
      broadcastEvents.clear();
      weappEmJsSdk.objCallBack({
        errMsg: 'unregisterAllBroadcast: ok',
      }, obj.success);
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `unregisterAllBroadcast: ${error}`
      }, obj.fail);
    }
  }

  static unregisterBroadcast(obj: any): void {
    try {
      const { name } = obj;
      if (!name) {
        throw new Error('name is empty');
      }

      if (broadcastEvents.has(name)) {
        broadcastEvents.delete(name);
      }

      weappEmJsSdk.objCallBack({
        errMsg: 'unregisterBroadcast: ok',
      }, obj.success);
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `unregisterBroadcast: ${error}`
      }, obj.fail);
    }
  }

  static registerBroadcast(obj: any): void {
    try {
      const { name, callback } = obj;
      if (!name || !callback) {
        throw new Error('name or callback is empty');
      }

      if (broadcastEvents.has(name)) {
        broadcastEvents.delete(name); // 如果有了 就删掉之前的
      }

      broadcastEvents.set(name, callback);
      weappEmJsSdk.objCallBack({
        errMsg: 'registerBroadcast: ok',
      }, obj.success);
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `registerBroadcast: ${error}`
      }, obj.fail);
    }
  }

  static postBroadcast(obj: any): void {
    try {
      const emr = emRequire();
      if (emr) {
        const { name, param } = obj;
        const { remote } = emr('electron');
        const allWindows = remote.BrowserWindow.getAllWindows();
        // const currentWin = remote.getCurrentWindow();
        allWindows.forEach((win: any) => {
          // if (win.id === currentWin.id) {
          //   return;
          // }

          win.webContents.send(broadcastIpcName, {
            name,
            param,
          });
        });
        weappEmJsSdk.objCallBack({
          errMsg: 'postBroadcast: ok',
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `postBroadcast: ${error}`
      }, obj.fail);
    }
  }

  static setWindowOpenHandler(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { remote } = emr('electron');
        const wc = remote.getCurrentWebContents();

        if (wc.setWindowOpenHandler) {
          wc.setWindowOpenHandler(obj.handler);
          weappEmJsSdk.objCallBack({
            errMsg: 'setWindowOpenHandler: ok',
          }, obj.success);
        } else {
          weappEmJsSdk.objCallBack({
            errMsg: `setWindowOpenHandler is not a Function`
          }, obj.fail);
        }
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `setWindowOpenHandler: ${error}`
      }, obj.fail);
    }
  }

  static closePcClientWindow(obj: any) {
    try {
      let remote: any = null;

      const emr = emRequire();
      if (emr) {
        remote = emr('electron').remote;
      }

      if (remote) {
        const wins = remote.BrowserWindow;
        const allWindows = wins.getAllWindows();

        if (allWindows.length > 0) {
          allWindows.forEach((w: any) => {
            const {
              oliType
            } = w || {};

            if (oliType === 'photo-view' || oliType === 'preference' || oliType === 'download' || oliType === 'popup' || oliType === 'update') {
              w.destroy();
            }
          });
        }

        weappEmJsSdk.objCallBack({
          errMsg: 'closePcClientWindow: ok',
        }, obj.success);
      } else {
        throw 'remote is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `closePcClientWindow: ${error}`
      }, obj.fail);
    }
  }

  static writeErrorLog(...args: any[]) {
    let ipcRenderer: any = null;

    const emr = emRequire();
    if (emr) {
      ipcRenderer = emr('electron').ipcRenderer;
    }

    if (ipcRenderer) {
      ipcRenderer.send('write-error-log', args);
    }
  }

  static independentPhotoView(obj: any) {
    try {
      let ipcRenderer: any = null;

      const emr = emRequire();
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        throttle(() => {
          const param: any = obj;

          const {
            className,
            data,
            fullScreenScale,
            imageClassName,
            loginFree,
            maskClassName,
            maskClosable,
            openGraphic,
            options,
            photoClosable,
            photoIndex,
            viewClassName,
            visible
          } = param;

          const finalParams: any = {
            className,
            data,
            fullScreenScale,
            imageClassName,
            loginFree,
            maskClassName,
            maskClosable,
            openGraphic,
            options,
            photoClosable,
            photoIndex,
            viewClassName,
            visible
          };

          const employeeId = window.TEAMS?.currentUser?.employeeId;
          const tenantKey = window.TEAMS?.currentTenant?.tenantKey;

          request({
            url: '/api/em/msg/checkEmployee',
            method: 'post',
            data: {
              employeeId,
              tenantKey
            }
          }).then((res: any) => {
            const {
              status,
              actionMsg
            } = res || {};

            const finalParamsStr: any = JSON.stringify(finalParams);

            if (actionMsg) {
              weappEmJsSdk.objCallBack({
                errMsg: `independentPhotoView: eteamsid error`
              }, obj.fail);

              weappEmJsSdk.writeErrorLog('independentPhotoView check eteamsid', res);
            } else if (!status) {
              weappEmJsSdk.objCallBack({
                errMsg: `independentPhotoView: eteamsid error`
              }, obj.fail);

              weappEmJsSdk.writeErrorLog('independentPhotoView check eteamsid', res);
            } else {
              ipcRenderer.send('show-photo-view', finalParamsStr);

              weappEmJsSdk.objCallBack({
                errMsg: 'independentPhotoView: ok',
              }, obj.success);
            }
          }).catch((error: any) => {
            weappEmJsSdk.objCallBack({
              errMsg: `independentPhotoView: ${error}`
            }, obj.fail);

            weappEmJsSdk.writeErrorLog('independentPhotoView check eteamsid', error);
          });
        }, 500)();
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `independentPhotoView: ${error}`
      }, obj.fail);
    }
  }

  static uploadFilePcClient(obj: any) {
    try {
      let ipcRenderer: any = null;

      const emr = emRequire();
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        const {
          files = [],
          shareUsers,
          shareGroups,
          shareExternals,
        } = obj;

        const eteamsid = window.ETEAMSID;

        const finalFiles: any = [];

        files.forEach((f: any) => {
          const {
            lastModified,
            name,
            path,
            size,
            type,
            uid,
            webkitRelativePath
          } = f;

          finalFiles.push({
            lastModified,
            name,
            path,
            size,
            type,
            uid,
            webkitRelativePath,
            shareUsers,
            shareGroups,
            shareExternals,
            eteamsid
          });
        });

        const param: any = {
          files: finalFiles
        };

        ipcRenderer.send('upload-file-pc-client', param);

        ipcRenderer.on('upload-file-pc-client.error', (event: any, args: any) => {
          weappEmJsSdk.objCallBack({
            errMsg: `uploadFilePcClient: fail`,
            error: args
          }, obj.fail);
        });

        ipcRenderer.on('upload-file-pc-client.finish', (event: any, args: any) => {
          weappEmJsSdk.objCallBack({
            errMsg: `uploadFilePcClient: finish`,
            data: args
          }, obj.finish);
        });

        ipcRenderer.on('upload-file-pc-client.progress', (event: any, args: any) => {
          weappEmJsSdk.objCallBack({
            errMsg: `uploadFilePcClient: progress`,
            data: args
          }, obj.progress);
        });

        weappEmJsSdk.objCallBack({
          errMsg: `uploadFilePcClient: ok`
        }, obj.success);
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `uploadFilePcClient: ${error}`
      }, obj.fail);
    }
  }

  static getUploadFiles(obj: any) {
    try {
      let ipcRenderer: any = null;

      const emr = emRequire();
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        const info = ipcRenderer.sendSync('get-upload-files') || {};

        weappEmJsSdk.objCallBack({
          ...info,
          errMsg: 'getUploadFiles: ok',
        }, obj.success);
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `getUploadFiles: ${error}`
      }, obj.fail);
    }
  }

  static switchServer(obj: any): void {
    try {
      const emr = emRequire();
      if (emr) {
        const { ipcRenderer } = emr('electron');
        ipcRenderer.send('set-global-varible', {
          name: 'auto-redirect',
          value: false,
          disk: true
        });

        relaunch();

        weappEmJsSdk.objCallBack({
          errMsg: 'switchServer: ok',
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `switchServer: ${error}`
      }, obj.fail);
    }
  }

  static systemIdentify(obj: any): void {
    try {
      const emr = emRequire();
      if (emr) {
        const { ipcRenderer } = emr('electron');
        const id = ipcRenderer.sendSync('get-machine-id');
        const name = ipcRenderer.sendSync('get-machine-name');

        weappEmJsSdk.objCallBack({
          errMsg: 'systemIdentify: ok',
          identify: id,
          name,
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `systemIdentify: ${error}`
      }, obj.fail);
    }
  }

  static chooseDirectroy(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { remote } = emr('electron');
        const { multi = false } = obj;
        const props = [
          'openDirectory',
          'createDirectory',
          'dontAddToRecent',
        ];

        if (multi) {
          props.push('multiSelections');
        }

        const currentWin = remote.getCurrentWindow();
        const folders = remote.dialog.showOpenDialogSync(currentWin, {
          properties: props
        });

        weappEmJsSdk.objCallBack({
          errMsg: 'chooseDirectroy: ok',
          folders,
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `chooseDirectroy: ${error}`
      }, obj.fail);
    }
  }

  static chooseFile(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { remote } = emr('electron');
        const { multi = false } = obj;
        const props = [
          'openFile',
          'createDirectory',
          'dontAddToRecent',
        ];

        if (multi) {
          props.push('multiSelections');
        }

        const currentWin = remote.getCurrentWindow();
        const files = remote.dialog.showOpenDialogSync(currentWin, {
          properties: props
        });

        weappEmJsSdk.objCallBack({
          errMsg: 'chooseFile: ok',
          files,
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `chooseFile: ${error}`
      }, obj.fail);
    }
  }

  static openSyncWindow(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { ipcRenderer } = emr('electron');
        ipcRenderer.send('open-sync-window');

        weappEmJsSdk.objCallBack({
          errMsg: 'openSyncWindow: ok',
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `openSyncWindow: ${error}`
      }, obj.fail);
    }
  }

  static openLocalFolder(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { dir } = obj;
        const fs = emr('fs');
        fs.stat(dir, (error: any, stats: any) => {
          if (error) {
            weappEmJsSdk.objCallBack({
              errMsg: `openLocalFolder: ${error}`
            }, obj.fail);
            return;
          }

          const { remote } = emr('electron');
          if (stats.isDirectory()) {
            const url = emr('url');
            const fileUrl = url.format({
              pathname: dir,
              protocol: 'file:',
              slashes: true,
            });

            console.info('open local folder', fileUrl);
            const is = emr('electron-is');
            is.osx()
              ? remote.shell.openExternal(fileUrl)
              : remote.shell.openPath(fileUrl);
          } else {
            remote.shell.showItemInFolder(dir);
          }
        });
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `openLocalFolder: ${error}`
      }, obj.fail);
    }
  }

  static getRuleSyncState(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { ipcRenderer } = emr('electron');
        ipcRenderer
          .invoke('get-rule-sync-state')
          .then((result: any) => {
            weappEmJsSdk.objCallBack({
              errMsg: 'getRuleSyncState: ok',
              state: result,
            }, obj.success);
          });
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `getRuleSyncState: ${error}`
      }, obj.fail);
    }
  }

  static subscribeRuleStateChange(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { ipcRenderer } = emr('electron');
        ipcRenderer.on('osync-rule-state-change', (evnet: any, args: any) => {
          const { id, state } = args;

          weappEmJsSdk.objCallBack({
            errMsg: 'subscribeRuleStateChange: ok',
            id,
            state,
          }, obj.onChange);
        });

        weappEmJsSdk.objCallBack({
          errMsg: 'subscribeRuleStateChange: ok',
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `subscribeRuleStateChange: ${error}`
      }, obj.fail);
    }
  }

  static getLastLoginInfo(obj: any) {
    try {
      let ipcRenderer: any = null;
      const emr = emRequire();
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer) {
        let info = ipcRenderer.sendSync('get-last-login-info') || {};
        weappEmJsSdk.objCallBack({
          ...info,
          errMsg: 'getLastLoginInfo: ok',
        }, obj.success);
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `getLastLoginInfo: ${error}`
      }, obj.fail);
    }
  }

  static getLangLabels(obj: any) {
    try {
      let ipcRenderer: any = null;
      const emr = emRequire();
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }
      if (ipcRenderer) {
        let langKeys = ipcRenderer.sendSync('get-lang-labels') || {};

        weappEmJsSdk.objCallBack({
          langKeys,
          errMsg: 'getLangLabels: ok',
        }, obj.success);
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `getLangLabels: ${error}`
      }, obj.fail);
    }
  }

  /**
   *
   * @param obj { localInfo :{ type:'语言:如zh-CN', version:'版本',label:{ '12312':'数据'  }},success:function(){},... }
   *            version 如果有就传一下
   */
  static setLangLabelInfo(obj: any) {
    try {
      let ipcRenderer: any = null;
      const emr = emRequire();
      if (emr) {
        ipcRenderer = emr('electron').ipcRenderer;
      }

      if (ipcRenderer && (obj?.localInfo)) {
        const type = langFormat(obj?.localInfo?.type);
        ipcRenderer.send('set-lang-label-info', {
          ...obj?.localInfo,
          type,
        })

        weappEmJsSdk.objCallBack({
          errMsg: 'setLangLabelInfo: ok',
        }, obj.success);
      } else {
        throw 'ipcRenderer is undefined';
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `setLangLabelInfo: ${error}`
      }, obj.fail);
    }
  }

  static syncRules(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { id } = obj;
        const { ipcRenderer } = emr('electron');
        ipcRenderer.send('sync-rule', { id });

        weappEmJsSdk.objCallBack({
          errMsg: 'syncRules: ok',
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `syncRules: ${error}`
      }, obj.fail);
    }
  }

  static noticeRuleChange(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { id } = obj;
        const { ipcRenderer } = emr('electron');
        ipcRenderer.send('notice-rule-change', { id });

        weappEmJsSdk.objCallBack({
          errMsg: 'noticeRuleChange: ok',
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `noticeRuleChange: ${error}`
      }, obj.fail);
    }
  }

  static downloadCloudFile(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const { ipcRenderer } = emr('electron');
        ipcRenderer.send('download-cloud-files', obj);

        weappEmJsSdk.objCallBack({
          errMsg: 'downloadCloudFile: ok',
        }, obj.success);
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `downloadCloudFile: ${error}`
      }, obj.fail);
    }
  }

  static uploadFileToCloud(obj: any) {
    try {
      const emr = emRequire();
      if (emr) {
        const syncId = uuid();
        const { ipcRenderer } = emr('electron');
        ipcRenderer.send('upload-files-to-cloud', {
          ...obj,
          syncId,
        });

        ipcRenderer.on('upload-files-to-cloud.success', (event: any, sid: string) => {
          if (syncId === sid) {
            weappEmJsSdk.objCallBack({
              errMsg: 'uploadFileToCloud: ok',
            }, obj.success);
          }
        });
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `uploadFileToCloud: ${error}`
      }, obj.fail);
    }
  }

  static joinMeeting(obj: any): void {
    try {
      const emr = emRequire();

      if (emr) {
        const { ipcRenderer } = emr('electron');

        const currentUser = window.TEAMS ? window.TEAMS.currentUser : {};
        const userName = currentUser.username;

        const {
          msgInfo,
          joinType,
          sdkInitInfo,
          meetingInfo,
          meetingConf,
          otherParams,
          sdkType,
          meetingCallback
        } = obj;

        const finalObj = {
          msgInfo,
          joinType,
          sdkInitInfo,
          meetingInfo,
          meetingConf,
          otherParams,
          sdkType,
          userName
        };

        weappEmJsSdk.meetingCallback = meetingCallback;

        if (ipcRenderer) {
          ipcRenderer.send('AllMeetingInfo', finalObj);

          ipcRenderer.once('AllMeetingInfo.result', (event: any, args: any) => {
            const {
              code,
              message
            } = args;

            if (code === 0) { // 成功
              weappEmJsSdk.objCallBack({
                errMsg: 'joinMeeting: ok',
              }, obj.success);
            } else {
              weappEmJsSdk.objCallBack({
                errMsg: `joinMeeting: ${code} ${message}`,
              }, obj.fail);
            }
          });

          ipcRenderer.on('meetingSDKCallback', (event: any, args: any) => {
            weappEmJsSdk.meetingCallback && weappEmJsSdk.meetingCallback(args);
          });
        } else {
          throw 'ipcRenderer is undefined';
        }
      }
    } catch (error) {
      weappEmJsSdk.objCallBack({
        errMsg: `joinMeeting: ${error}`
      }, obj.fail);
    }
  }

  static ready(params: any, callback: Function = () => { }): void {
    console.error('e10 app ready start');

    let finalCallback = callback; // 兼容云桥

    if (params && Object.prototype.toString.apply(params) === '[object Function]') {  // 如果不是function, 忽略
      finalCallback = params;
    }

    if (finalCallback && Object.prototype.toString.apply(finalCallback) === '[object Function]') {
      const getIsOk = (isOkType: string): any => {
        let isOk = false;

        if (isOkType === 'isE10AppOk') {
          isOk = weappEmJsSdk.isE10AppOk;
        }

        if (isOkType === 'isE10PcOk') {
          isOk = weappEmJsSdk.isE10PcOk;
        }

        if (isOkType === 'isPCIframeOk') {
          isOk = weappEmJsSdk.isPCIframeOk;
        }

        return isOk;
      }

      const intervalCallback = (isOkType: string) => {
        let isOk = getIsOk(isOkType);

        if (isOk) { // app 已经准备好了
          console.error('e10 is ok getAllSupport back');

          finalCallback();
          return;
        }

        let readyInterval: any = setInterval(() => {
          let isOk = getIsOk(isOkType);

          if (isOk) {
            console.error('e10 is ok getAllSupport back');

            clearInterval(readyInterval);
            readyInterval = null;
            finalCallback();
          }
        }, 100);

        if (isOkType === 'isE10AppOk') { // 手机端等10s吧，因为有getAllSupportJsApi
          setTimeout(() => {  // 10秒之后ready必执行
            let isOk = getIsOk(isOkType);

            if (!isOk) {
              console.error('e10 app is ok getAllSupport no back');

              clearInterval(readyInterval);
              readyInterval = null;
              finalCallback();
            }
          }, 10 * 1000);
        } else {
          setTimeout(() => {  // 3秒之后ready必执行
            let isOk = getIsOk(isOkType);

            if (!isOk) {
              console.error('e10 pc is ok getAllSupport no back');

              clearInterval(readyInterval);
              readyInterval = null;
              finalCallback();
            }
          }, 3 * 1000);
        }
      }

      if (weappEmJsSdk.inE10APP()) {
        intervalCallback('isE10AppOk');
        return;
      }

      if (weappEmJsSdk.inAndroid() || weappEmJsSdk.inIphone()) {  // 在移动端h5浏览器页面
        finalCallback();
        return;
      }

      if (weappEmJsSdk.inE10Pc()) {  // pc环境
        intervalCallback('isE10PcOk');
        return;
      }

      intervalCallback('isPCIframeOk');
    }
  }

  static postMsg(funcName: string, obj: any = {}): void {
    if (obj && Object.prototype.toString.apply(obj) === '[object Object]') {
      const {
        fail,
        success,
        callback
      } = obj;

      if (success) {
        weappEmJsSdk.iframeSuccess[funcName] = success;
      }

      if (fail) {
        weappEmJsSdk.iframeFail[funcName] = fail;
      }

      if (callback) {
        if (funcName === REGISTER_IM_NOTICE_FUNCNAME) {
          const {
            cmd,
            type,
            msgType
          } = obj;

          let funcKey = funcName;

          if (type) {
            funcKey = `${REGISTER_IM_NOTICE_FUNCNAME}-${cmd}-${type}`;
          } else if (msgType) {
            funcKey = `${REGISTER_IM_NOTICE_FUNCNAME}-${cmd}-${msgType}`;
          }

          weappEmJsSdk.iframeCallback[funcKey] = callback;
        }
      }

      delete obj.success;
      delete obj.fail;
      delete obj.callback;

      window.parent.postMessage({
        type: POST_MESSAGE_TYPE,
        funcName: funcName,
        data: JSON.stringify(obj),
        trackId: weappEmJsSdk.pcTrackId
      }, '*');
    }

    if (obj && Object.prototype.toString.apply(obj) === '[object Function]') {
      if (funcName === PAGEVISIBLE_FUNCNAME) {
        weappEmJsSdk.iframeCallback[PAGEVISIBLE_FUNCNAME] = obj;
      }

      window.parent.postMessage({
        type: POST_MESSAGE_TYPE,
        funcName: funcName,
        trackId: weappEmJsSdk.pcTrackId
      }, '*');
    }
  }
}

export const ready = weappEmJsSdk.ready;
export const invoke = weappEmJsSdk.invoke;
export const checkJsApi = weappEmJsSdk.checkJsApi;
export default new weappEmJsSdk();
